/*
 * @Author: czy
 * @Date: 2021-07-10 14:33:21
 * @LastEditTime: 2021-07-15 09:39:11
 */
#include "sys/syscall.h"
#include "sys/system.h"

/**
 * @description: The system calls the unified interface, which has two four byte parameters and a four byte return value.
 * @param num   System call number (passed through eax).
 * @param arg1  Parameter 1 (passed through edx).
 * @param arg2  Parameter 2 (passed through ecx).
 * @return Return value (passed through eax).
 */
__attribute__((regparm(3))) int _syscall(int num, int arg1, int arg2)
{
    int val;
    __asm__ __volatile__("int $0x80");
    return_val(val);
    return val;
}

/**
 * @description: System call handler.
 * @param num   System call number (passed through eax).
 * @param arg1  Parameter 1 (passed through edx).
 * @param arg2  Parameter 2 (passed through ecx).
 * @return Return value (passed through eax).
 */
__attribute__((regparm(3))) int syscall(int num, int arg1, int arg2)
{
    // Must turn on the interrupt first.
    __asm__ __volatile__("sti");

    int result = 0;
    switch (num)
    {
    case CLS:
        // void cls(void);
        cls();
        break;
    case GETC:
        // int getc(void);
        result = getc();
        break;
    case PUTC:
        // int putc(int ch);
        result = putc(arg1);
        break;
    case READ:
        // char *read(char *str, const char *promrt);
        result = (int)(read((char *)arg1, (const char *)arg2));
        break;
    case WRITE:
        // int write(char *buf);
        write((char *)arg1);
        break;
    case TIMER:
        // int timer(void (*func)(void), int interval);
        result = timer((void (*)(void))arg1, arg2);
        break;
    case SETTIMEOUT:
        // int setTimeout(void (*func)(void), int interval);
        result = setTimeout((void (*)(void))arg1, arg2);
        break;
    case CANCELTSK:
        // void cancelTsk(int tskId);
        cancelTsk(arg1);
        break;
    case CLI:
        // void cli(void);
        cli();
        break;
    case STI:
        // void sti(void);
        sti();
        break;
    case BRK:
        // void *brk(void);
        result = (int)(brk());
        break;
    case STARTSHELL:
        // void startShell(void);
        startShell();
        break;
    case GETTIME:
        // void gettime(time_t *time);
        gettime((time_t *)arg1);
        break;
    case SETTIME:
        // void settime(time_t *time);
        settime((time_t *)arg1);
        break;
    case GETENV:
        // void *getenv(char *name);
        result = (int)(getenv((char *)arg1));
        break;
    case SETENV:
        // void setenv(char *name, void *value);
        setenv((char *)arg1, (void *)arg2);
        break;
    case CREATEPROCESS:
        // int createProcess(int (*tskBody)(void));
        result = createProcess((int (*)(void))arg1);
        break;
    case DESTROYPROCESS:
        // void destroyProcess(int tskIndex);
        destroyProcess(arg1);
        break;
    case PROCESSSTART:
        // void processStart(int tskIndex);
        processStart(arg1);
        break;
    case PROCESSEND:
        // void processEnd(void);
        processEnd();
        break;
    }
    if (num < CREATEPROCESS)
    {
        processSwitch();
    }
    return result;
}